#ifndef __TLISTACOM_H__
#define __TLISTACOM_H__


#include "tcomplejo.h" 
#include <iostream>
using namespace std;
//! \file tlistacom.h
//! \brief Cabeceras de la clase TListaCom, TListaNodo y TListaPos

class TListaCom;

//! \class TListaNodo
/*!	\brief Nodos para la lista TListaCom*/

class TListaNodo
{
	friend class TListaPos;
	friend class TListaCom;
	public:
		//! \brief Constructor por defecto de TListaNodo
		/*!	Construye un objeto de tipo TListaNodo sin parámetros*/
		TListaNodo ();
		//! \brief Constructor de copia de TListaNodo
		/*!	Construye un objeto de tipo TListaNodo a partir de otro*/
		TListaNodo (const TListaNodo &);
		//! \brief Destructor de TListaNodo
		/*!	Pone a 0 todos los campos*/
		~TListaNodo ();
		//! \brief Operator = de TListaNodo
		/*!	Asigna un objeto de tipo TListaNodo a otro*/
		TListaNodo & operator=(const TListaNodo &);

		friend ostream & operator<<(ostream &, const TListaCom &);
	private:
		//! \brief TComplejo e
		/*!	Contiene el valor del nodo*/
		TComplejo e;
		//! \brief TListaNodo *anterior
		/*!	Apunta al nodo anterior*/
		TListaNodo *anterior;
		//! \brief TListaNodo *siguiente
		/*!	Apunta al nodo siguiente*/
		TListaNodo *siguiente;
};


//! \class TListaPos
/*!	\brief Clase que almacena un puntero a un nodo de la lista*/

class TListaPos
{
	friend class TListaCom;
	public:
		//! \brief Constructor por defecto de TListaPos
		/*!	Construye un objeto de tipo TListaPos*/
		TListaPos ():pos(0){};
		//! \brief Constructor de copia de TListaPos
		/*!	Construye un TListaPos a partir de otro*/
		TListaPos (const TListaPos &);
		//! \brief Destructor de TListaPos
		/*!	Pone a 0 todos sus campos*/
		~TListaPos ();
		//! \brief Operator = de TListaPos
		/*!	Asigna un TListaPos a otro*/
		TListaPos & operator=(const TListaPos &);
		//! \brief Operator == de TListaPos
		/*!	Devuelve true si ambos son iguales*/
		bool operator==(const TListaPos & p)const;
		//! \brief Operator != de TListaPos
		/*!	Devuelve true si son distintos*/
		bool operator!=(const TListaPos & p)const;
		//! \brief Anterior
		/*!	Devuelve un TListaPos que apunta al nodo anterior*/
		TListaPos Anterior() const;
		//! \brief Siguiente
		/*!	Devuelve un TListaPos que apunta al nodo siguiente*/
		TListaPos Siguiente() const;
		//! \brief EsVacia
		/*!	Devuelve true si el objeto no apunta a ningun TListaNodo*/
		bool EsVacia(){return pos == NULL;};

		friend ostream & operator<<(ostream &, const TListaCom &);
	private:
		//! \brief TListaNodo *pos
		/*!	Apunta a un TListaNodo*/
		TListaNodo *pos;

};

//! \class TListaCom
/*!	\brief Clase que maneja una lista*/

class TListaCom
{
	public:
		//! \brief Constructor por defecto de TListaCom
		/*!	Construye un objeto de tipo TListaCom sin parametros*/
		TListaCom ():primero(NULL), ultimo(NULL){};
		//! \brief Constructor de copia de TListaCom
		/*!	Construye un TListaCom a partir de otro*/
		TListaCom (const TListaCom &);
		//! \brief Destructor de TListaCom
		/*!	Libera la memoria dinámica de la lista de complejos*/
		~TListaCom ();
		//! \brief Operator = de TListaCom
		/*!	Asigna una lista a otra*/
		TListaCom & operator=(const TListaCom &);
		//! \brief Operator == de TListaCom
		/*!	Devuelve true si 2 listas tienen los mismos elementos en el mismo orden*/
		bool operator==(const TListaCom &) const;
		//! \brief Operator != de TListaCom
		/*!	Devuelve true si las listas son distintas*/
		bool operator!=(const TListaCom &) const;
		//! \brief Operator + de TListaCom
		/*!	Devuelve una lista producto de concatenar las 2 listas*/
		TListaCom operator+(const TListaCom &) const;
		//! \brief Operator - de TListaCom
		/*!	Devuelve una lista que contiene los elementos de this que no estan en el argumento*/
		TListaCom operator-(const TListaCom &) const;
		//! \brief EsVacia
		/*!	Devuelve true si la lista es vacia*/
		bool EsVacia() const;
		//! \brief InsCabeza
		/*!	Añade un TComplejo delante de la lista.*/
		bool InsCabeza(const TComplejo &);
		//! \brief InsCola
		/*! Inserta un complejo al final de la lista (private)*/
		bool InsCola(const TComplejo &);
		//! \brief InsertarI
		/*!	Añade un TComplejo a la izquierda de la posicion dada, siempre y cuando pertenezca a la lista*/
		bool InsertarI(const TComplejo &, const TListaPos &);
		//! \brief InsertarD
		/*!	Añade un TComplejo a la derecha de la posicion dada, siempre que pertenezca a la lista*/
		bool InsertarD(const TComplejo &, const TListaPos &);
		//! \brief Borrar (TComplejo)
		/*!	Borra la primera aparición de un TComplejo*/
		bool Borrar(const TComplejo &);
		//! \brief BorrarTodos
		/*!	Borra todas las apariciones de un TComplejo*/
		bool BorrarTodos(const TComplejo &);
		//! \brief Borrar (TlistaPos)
		/*!	Borra la posicion indicada si pertenece a la lista*/
		bool Borrar(const TListaPos &);
		//! \brief Obtener
		/*!	Devuelve el valor del complejo almacenado en la posicion dada, si esta pertenece a la lista*/
		TComplejo Obtener(const TListaPos &) const;
		//! \brief Buscar
		/*!	Devuelve true si el complejo existe en la lista*/
		bool Buscar(const TComplejo &) const;
		//! \brief Longitud
		/*!	Devuelve la longitud de la lista*/
		int Longitud() const;
		//! \brief Primera
		/*!	Devuelve un TListaPos que apunta al primer elemento de la lista*/
		TListaPos Primera() const;
		//! \brief Ultima
		/*!	Devuelve un TListaPos que apunta al ultimo elemento de la lista*/
		TListaPos Ultima() const;

		//! \brief Operator << de TListaCom
		/*!	Saca por pantalla una lista entre {}*/
		friend ostream & operator<<(ostream &, const TListaCom &);
		
	private:
		//! \brief TListaNodo *primero
		/*!	Primer TListaNodo de la lista*/
		TListaNodo *primero;
		//! \brief TListaNodo *ultimo
		/*!	Ultimo TListaNodo de la lista*/
		TListaNodo *ultimo;
		//! \brief PerteneceALista
		/*!	Devuelve true si una TListaPos pertenece a la lista (private)*/
		bool PerteneceALista(const TListaPos &) const;

};
#endif
